Skip to content

Conversation

@henriquemoody
Copy link
Member

I wanted to create a way to build dynamic, context-aware messages, similar to what we currently have in the Validation component. My long-term goal is to decouple string formatting from Validation and centralize it here in StringFormatter. This commit introduces the PlaceholderFormatter, which brings a familiar {{placeholder}} syntax to our toolkit.

Recognizing that creating a new object for every unique template can be cumbersome, I have introduced the formatWith() method. This allows for additional data injection at call-time. However, to maintain predictability, I’ve established a clear hierarchy: parameters provided in the constructor are treated as the "primary" configuration and will always take precedence over call-time parameters. This ensures that a pre-configured formatter behaves consistently even when used in a dynamic context.

By moving this logic here, we lay the groundwork for a more modular system where formatting is a first-class citizen rather than a utility hidden inside other components.

Assisted-by: Claude Code (Opus 4.5)

@codecov-commenter
Copy link

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces the PlaceholderFormatter class to enable dynamic, context-aware message building using a {{placeholder}} syntax. The implementation aims to decouple string formatting from other components and centralize it as a first-class feature. It includes comprehensive testing and detailed documentation.

Changes:

  • Adds PlaceholderFormatter class with support for template interpolation using {{placeholder}} syntax
  • Introduces formatWith() method for runtime parameter injection with constructor precedence
  • Adds respect/stringifier dependency for type conversions

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/PlaceholderFormatter.php Core implementation of placeholder-based template formatter with regex pattern matching and stringifier integration
tests/Unit/PlaceholderFormatterTest.php Comprehensive test suite covering basic interpolation, type conversions, edge cases, Unicode support, and formatWith behavior
docs/PlaceholderFormatter.md Detailed documentation including API reference, type handling, examples, and use cases
composer.json Adds respect/stringifier ^3.0 dependency and updates PHP version requirement
README.md Updates formatter table to include PlaceholderFormatter

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

I wanted to create a way to build dynamic, context-aware messages, similar to
what we currently have in the Validation component. My long-term goal is to
decouple string formatting from Validation and centralize it here in
StringFormatter. This commit introduces the `PlaceholderFormatter`, which
brings a familiar `{{placeholder}}` syntax to our toolkit.

Recognizing that creating a new object for every unique template can be
cumbersome, I have introduced the `formatWith()` method. This allows for
additional data injection at call-time. However, to maintain predictability,
I’ve established a clear hierarchy: parameters provided in the constructor are
treated as the "primary" configuration and will always take precedence over
call-time parameters. This ensures that a pre-configured formatter behaves
consistently even when used in a dynamic context.

By moving this logic here, we lay the groundwork for a more modular system
where formatting is a first-class citizen rather than a utility hidden
inside other components.

Assisted-by: Claude Code (Opus 4.5)
@henriquemoody henriquemoody force-pushed the placeholder branch 2 times, most recently from 71f9492 to f5f216a Compare January 19, 2026 12:05
@henriquemoody henriquemoody merged commit f5f216a into Respect:main Jan 19, 2026
3 checks passed
@henriquemoody henriquemoody deleted the placeholder branch January 19, 2026 12:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants